package com.zmn.oms.admin.controller.work.modify;

import com.alibaba.fastjson.JSON;
import com.zmn.base.common.data.common.dro.tags.TagsDRO;
import com.zmn.common.constant.GlobalConsts;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.utils.collection.CollectionUtil;
import com.zmn.common.utils.date.DateUtil;
import com.zmn.common.utils.number.NumberUtil;
import com.zmn.common.utils.string.StringUtil;
import com.zmn.mcc.cas.model.LoginStaff;
import com.zmn.mcc.common.dto.dept.DeptDRO;
import com.zmn.mcc.common.dto.staff.StaffDRO;
import com.zmn.mcc.dubbo.interfaces.dept.DeptListRemoteService;
import com.zmn.mcc.dubbo.interfaces.staff.StaffListRemoteService;
import com.zmn.oms.admin.controller.work.WorkBaseController;
import com.zmn.oms.business.interfaces.base.BaseCodeService;
import com.zmn.oms.business.interfaces.remark.OrderRemarkBService;
import com.zmn.oms.common.constant.OrderConsts;
import com.zmn.oms.common.constant.OrderRefundConsts;
import com.zmn.oms.common.constant.OrderStatusConsts;
import com.zmn.oms.common.dto.ResultDTO;
import com.zmn.oms.common.exception.OmsBaseException;
import com.zmn.oms.model.dto.order.ConfirmDTO;
import com.zmn.oms.model.dto.work.refund.RefundDTO;
import com.zmn.oms.model.entity.master.OrderMaster;
import com.zmn.oms.model.entity.pay.OrderPay;
import com.zmn.oms.model.entity.work.OrderWork;
import com.zmn.oms.model.vo.remark.OrderRemarkVO;
import com.zmn.oms.model.vo.work.OperatePermissionVO;
import com.zmn.oms.model.vo.work.refund.RefundVO;
import com.zmn.oms.services.interfaces.master.OrderMasterService;
import com.zmn.oms.services.interfaces.pay.OrderPayService;
import com.zmn.oms.zmn.business.interfaces.order.ZsOrderBService;
import com.zmn.oms.zmn.business.interfaces.work.ZsOrderWorkOperatePermissionBService;
import com.zmn.oms.zmn.normal.business.interfaces.refund.RefundBService;
import com.zmn.pay.common.constant.PayConsts;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 类描述：退款金额
 * @author liuying
 * @date 2018/12/17 20:18
 */
@Controller
@RequestMapping("/work/modify")
public class WorkRefundController extends WorkBaseController {

    @Autowired
    private RefundBService refundBService;
    @Autowired
    private ZsOrderBService zsOrderBService;
    @Autowired
    OrderRemarkBService orderRemarkBService;
    @Autowired
    OrderPayService orderPayService;
    @Autowired
    private BaseCodeService baseCodeService;

    @Autowired
    private ZsOrderWorkOperatePermissionBService orderWorkOperatePermissionBService;

    @Autowired
    private OrderMasterService orderMasterService;

    @Reference(version = com.zmn.mcc.dubbo.dto.DubboConsts.INTERFACE_VERSION, check = false)
    StaffListRemoteService staffListRemoteService;
    @Reference(check = false, version = com.zmn.mcc.dubbo.dto.DubboConsts.INTERFACE_VERSION)
    DeptListRemoteService deptListRemoteService;

    /**
     * 退款金额
     */
    @RequestMapping(value = "/refund")
    public ModelAndView refund(Long orderId, Long workId, Integer moduleId) throws OmsBaseException {
        ModelAndView mv = new ModelAndView("work/modify/refund");
        RefundVO refundVO = refundBService.getRefundVO(orderId, workId, false);
        mv.addObject("refundVO", refundVO);
        mv.addObject("orderId", orderId);
        mv.addObject("workId", workId);
        mv.addObject("maxRefundAmount", refundVO.getOriginalAmount() - refundVO.getHaveRefundAmount());
        if (refundVO.isSupportBacktracking()) {
            mv.addObject("maxBacktrackingAmount", refundVO.getBacktrackingAmount() - refundVO.getHaveBacktrackingAmount());
        } else {
            mv.addObject("maxBacktrackingAmount", 0);
        }
        mv.addObject("moduleId", moduleId);
        // 是否
        mv.addObject("yesOrNo", OrderConsts.getYesOrNoObj());
        // 修改标识
        mv.addObject("isUpdate", false);
        return mv;
    }

    /**
     * 修改退款单
     */
    @RequestMapping(value = "/update/refund")
    @ResponseBody
    public ResultDTO updateRefund(@RequestBody RefundDTO refundDTO) {
        logger.debug("退款修改[{}]", refundDTO);

        OperatePermissionVO operatePermission = orderWorkOperatePermissionBService
                .getOperatePermission(refundDTO.getOrderId(), refundDTO.getWorkId(), OrderConsts.ORDER_OP_TYPE_UPDATE);
        if (!operatePermission.getCanOperate()) {
            return ResultDTO.fail(operatePermission.getMsg());
        }
        try {
            // 判断是否需要审批
            this.isRefundReview(refundDTO);
            refundDTO.setDTalkId(this.getDTalkId());

            OrderWork orderWork = null;
            OrderPay refundPay = orderPayService.getOrderWorkRefundPay(refundDTO.getOrderId(), refundDTO.getWorkId());
            // 备注
            OrderRemarkVO orderRemarkVO = orderRemarkBService.findOrderRemarkVO(refundDTO.getOrderId(), refundDTO.getWorkId(), OrderConsts.ORDER_REMARK_TYPE_REFUND);
            refundDTO.setHistoryOrderPay(refundPay);
            refundDTO.setHistoryRemark(orderRemarkVO);
            if (Objects.equals(refundDTO.getOpType(), OrderConsts.ORDER_OP_TYPE_CONFIRM)) {
                Boolean isUpdate = this.isUpdate(refundDTO);
                if (isUpdate) {
                    orderWork = refundBService.updateRefund(refundDTO);
                } else {
                    orderWork = orderWorkService.findOrderWorkByKey(refundDTO.getOrderId(), refundDTO.getWorkId());
                }
                // 自动确认
                ConfirmDTO confirmDTO = new ConfirmDTO();
                confirmDTO.setOrderId(refundDTO.getOrderId());
                confirmDTO.setWorkId(refundDTO.getWorkId());
                confirmDTO.setStatus(OrderStatusConsts.WORK_STATUS_CONFIRM);
                confirmDTO.setConfirmerId((long) GlobalConsts.OPERATE_USER_TYPE_SYSTEM);
                confirmDTO.setConfirmTime(DateUtil.getNow());
                confirmDTO.setOperator(refundDTO.getOperator());
                confirmDTO.setOperatorId(refundDTO.getOperatorId());
                confirmDTO.setOperatorType(refundDTO.getOperatorType());
                zsOrderBService.confirmOrderSimple(confirmDTO);
            } else {
                orderWork = refundBService.updateRefund(refundDTO);
            }
            logger.info("{}", orderWork);
            return ResultDTO.success(orderWork);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            return ResultDTO.fail(e.getMessage());
        }
    }

    /**
     * 是否修改过退款单
     * @param refundDTO
     * @return
     */
    private boolean isUpdate(RefundDTO refundDTO) {
        logger.debug("退款单开始比较：【{}】", JSON.toJSONString(refundDTO));
        OrderPay orderPay = refundDTO.getHistoryOrderPay();
        // 比较退款方式
        if (!Objects.equals(refundDTO.getRefundType(), orderPay.getRefundType())){
            return true;
        }
        // 非原路退
        if (!Objects.equals(refundDTO.getRefundType(), OrderConsts.ORDER_REFUND_TYPE_ONLINE)) {
            // 比较目标支付渠道
            if (!Objects.equals(refundDTO.getPayTargetChannelId(), orderPay.getPayTargetChannelId())) {
                return true;
            }
            // 比较支付账户
            if (!Objects.equals(refundDTO.getPayeeThirdAccount(), orderPay.getPayeeThirdAccount())) {
                return true;
            }
            // 比较账户名称
            if (!Objects.equals(refundDTO.getPayeeThirdAccountName(), orderPay.getPayeeThirdAccountName())) {
                return true;
            }
            // 比较打款银行
            if (Objects.equals(refundDTO.getPayTargetChannelId(), PayConsts.PAY_CHANNEL_PLATFORM_BANKTRANSFER)
                    && !Objects.equals(refundDTO.getPayeeThirdAccountBank(), orderPay.getPayeeThirdAccountBank())) {
                return true;
            }
        }
        // 比较金额
        if (!Objects.equals(refundDTO.getRefundAmount(), orderPay.getAmount())) {
            return true;
        }
        // 比较退款缘由
        if (!Objects.equals(refundDTO.getReasonList().get(0).getText(), refundDTO.getHistoryRemark().getDetailVOList().get(0).getMapName())){
            return true;
        }
        // 比较备注
        if (!Objects.equals(StringUtils.defaultString(refundDTO.getContent()), StringUtils.defaultString(refundDTO.getHistoryRemark().getContent()))) {
            return true;
        }
        return false;
    }

    /**
     * 保存退款单
     */
    @RequestMapping(value = "/save/refund")
    @ResponseBody
    public ResultDTO saveRefund(@RequestBody RefundDTO refundDTO) {
        logger.debug("退款提交[{}]", refundDTO);

        OperatePermissionVO operatePermission = orderWorkOperatePermissionBService
                .getOperatePermission(refundDTO.getOrderId(), refundDTO.getWorkId(), OrderConsts.ORDER_OP_TYPE_REFUND);
        if (!operatePermission.getCanOperate()) {
            return ResultDTO.fail(operatePermission.getMsg());
        }

        // 处理师傅数据，默认为原单的师傅信息
        OrderWork originalOrderWork = orderWorkService.findOrderWorkByKey(refundDTO.getOrderId(), refundDTO.getWorkId());
        refundDTO.setMasterId(originalOrderWork.getMasterId());
        refundDTO.setMasterName(originalOrderWork.getMasterName());
        refundDTO.setBizMode(originalOrderWork.getBizMode());
        if (Objects.equals(originalOrderWork.getMultiMaster(), GlobalConsts.YES)) {
            // 工程师列表
            List<OrderMaster> masters = orderMasterService.listMasterByWorkId(originalOrderWork.getOrderId(), originalOrderWork.getWorkId());

            List<Integer> masterIdList = masters.stream().filter(master -> Objects.equals(master.getType(), OrderConsts.ORDER_MASTER_TYPE_SLAVE)).map(OrderMaster::getMasterId).collect(Collectors.toList());

            refundDTO.setMasterList(masterIdList);
        }
        try {
            // 判断是否需要审批
            this.isRefundReview(refundDTO);
            refundDTO.setDTalkId(this.getDTalkId());

            OrderWork orderWork = refundBService.commitRefund(refundDTO);
            logger.info("{}", orderWork);
            // 成功后生成 退款记录
            //orderPayBService.syncGenerateRefundOrderPay(orderWork, refundDTO);
            return ResultDTO.success(orderWork);
        } catch (OmsBaseException e) {
            return ResultDTO.fail(e.getMessage());
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            return ResultDTO.fail(e.getMessage());
        }
    }

    /**
     * 总公司，品质保障部 角色 需要审核
     *
     * @return
     */
    private void isRefundReview(RefundDTO refundDTO) throws OmsBaseException {
        // 是否 总部，品质保障部 角色，用户处理审批逻辑
        boolean isBranchCompany = super.isBranchCompany();
        logger.info("isBranchCompany = {}",isBranchCompany);

        LoginStaff loginStaff = super.getLoginStaff();
        logger.info("loginStaff.deptId = {}", loginStaff.getDeptId());

        /*Set<Integer> deptList = new HashSet<>();
        ResponseDTO<List<DeptDRO>> listResponseDTO = deptListRemoteService.listDeptByIdAndKeyWord(OrderConsts.QUALITY_CONTROL_DEPARTMENT_DEPT_ID, null);
        logger.info("deptListRemoteService.listDeptByIdAndKeyWord params={},result={}", OrderConsts.QUALITY_CONTROL_DEPARTMENT_DEPT_ID, JSON.toJSONString(listResponseDTO));
        if (listResponseDTO.isSuccess()) {
            Set<Integer> deptIds = Optional.ofNullable(listResponseDTO.getData()).orElse(Collections.emptyList())
                    .stream()
                    .map(DeptDRO::getDeptId)
                    .collect(Collectors.toSet());
            deptList.addAll(deptIds);
        }

        ResponseDTO<List<DeptDRO>> listResponseDTO1 = deptListRemoteService.listDeptByIdAndKeyWord(OrderConsts.QUALITY_CONTROL_DEPARTMENT_DEPT_ID_NEW, null);
        logger.info("deptListRemoteService.listDeptByIdAndKeyWord params={},result={}", OrderConsts.QUALITY_CONTROL_DEPARTMENT_DEPT_ID_NEW, JSON.toJSONString(listResponseDTO1));
        if (listResponseDTO1.isSuccess()) {
            Set<Integer> deptIds = Optional.ofNullable(listResponseDTO1.getData()).orElse(Collections.emptyList())
                    .stream()
                    .map(DeptDRO::getDeptId)
                    .collect(Collectors.toSet());
            deptList.addAll(deptIds);
        }*/

        // 查询需要审批的退款部门
        List<TagsDRO> droList = baseCodeService.listBaseCodeMap(GlobalConsts.PLAT_MARK_ZMN, OrderRefundConsts.BASE_CODE_MAP_ONE_TYPE_REVIEW_DEPT_ID, null, null);
        logger.info("查询退款部门公共配置出参：【{}】", JSON.toJSONString(droList));
        if (CollectionUtil.isNullOrEmpty(droList)) {
            return;
        }

        for (TagsDRO dro : droList) {

            // 如果二级分类id为空，跳出本次循环
            if (NumberUtil.isNullOrZero(dro.getTwoTypeId())) {
                continue;
            }

            if (Objects.equals(dro.getTwoTypeId(), loginStaff.getDeptId())) {
                if (NumberUtil.isNullOrZero(dro.getThreeTypeId())) {
                    throw new OmsBaseException("当前操作钉钉组织部门为空");
                }
                refundDTO.setReview(!isBranchCompany);
                refundDTO.setDingTalkDeptId(Long.valueOf(dro.getThreeTypeId()));
            }

            ResponseDTO<List<DeptDRO>> listResponseDTO = deptListRemoteService.listDeptByIdAndKeyWord(dro.getTwoTypeId(), null);
            logger.info("deptListRemoteService.listDeptByIdAndKeyWord params={},result={}", dro.getTwoTypeId(), JSON.toJSONString(listResponseDTO));
            if (listResponseDTO.isSuccess()) {
                Set<Integer> deptIds = Optional.ofNullable(listResponseDTO.getData()).orElse(Collections.emptyList())
                        .stream()
                        .map(DeptDRO::getDeptId)
                        .collect(Collectors.toSet());
                if (deptIds.contains(loginStaff.getDeptId())) {
                    if (NumberUtil.isNullOrZero(dro.getThreeTypeId())) {
                        throw new OmsBaseException("当前操作钉钉组织部门为空");
                    }
                    refundDTO.setReview(!isBranchCompany);
                    refundDTO.setDingTalkDeptId(Long.valueOf(dro.getThreeTypeId()));
                    return;
                }
            }
        }
    }

    /**
     * 获取与昂工钉钉id
     * @return
     * @throws OmsBaseException
     */
    private String getDTalkId() throws OmsBaseException{
        ResponseDTO<StaffDRO> staff = staffListRemoteService.getStaff(super.getLoginStaff().getStaffId());
        if (staff.isSuccess() && Objects.nonNull(staff.getData()) && StringUtil.isNotBlank(staff.getData().getDTalkId())) {
            return staff.getData().getDTalkId();
        }
        throw new OmsBaseException("当前操作人钉钉id为空！");
    }
}
